package gatperdut.chato.core.interpreter.actions;

import gatperdut.chato.constants.CSConstantsCommandResult.CommandExecutionResult;
import gatperdut.chato.core.characters.BaseController;
import gatperdut.chato.core.interpreter.actions.generic.ManipulationAction;
import gatperdut.chato.core.interpreter.grammar.comminfo.ManipulationContainerInfo;
import gatperdut.chato.core.item.ItemController;

public class ManipulationContainerAction extends ManipulationAction {

    public ManipulationContainerAction( ManipulationContainerInfo info, BaseController entityController ) {
        super( info, entityController );
    }

    @Override
    public CommandExecutionResult perform() {
        checkForRunningCraft();

        String emote = getLastPartEmote();
        if ( emote == null ) {
            getEntityController().tx( "Check your emote." );
            return CommandExecutionResult.OK;
        }

        // --manipulating object?
        ItemController ic = findInRoomOrInventory( getInfo().getWhat(), getInfo().isGround() );
        if ( ic == null ) {
            getEntityController().tx( "You cannot find that here." );
            return CommandExecutionResult.OK;
        }

        if ( ic.getInventoryController() == null ) {
            getEntityController().tx( ic.getShortDesc() + " is not a container." );
            return CommandExecutionResult.OK;
        }

        switch ( getInfo().getManipulationType() ) {
        case CLOSE:
            if ( !ic.getItem().getInventory().isClosable() ) {
                getEntityController().tx( ic.getShortDesc() + " cannot be opened nor closed." );
                return CommandExecutionResult.OK;
            }
            if ( !ic.getItem().getInventory().isOpen() ) {
                getEntityController().tx( ic.getShortDesc() + " is already closed." );
                return CommandExecutionResult.OK;
            }

            ic.getItem().getInventory().setOpen( false );

            getEntityController().getEchoes().txCloseContainer( ic, emote );

            return CommandExecutionResult.OK;
        case OPEN:
            if ( !ic.getItem().getInventory().isClosable() ) {
                getEntityController().tx( ic.getShortDesc() + " cannot be opened nor closed." );
                return CommandExecutionResult.OK;
            }
            if ( ic.isLockable() && ic.getLockController().isLocked() ) {
                getEntityController().tx( ic.getShortDesc() + " is locked." );
                return CommandExecutionResult.OK;
            }
            if ( ic.getItem().getInventory().isOpen() ) {
                getEntityController().tx( ic.getShortDesc() + " is already open." );
                return CommandExecutionResult.OK;
            }

            ic.getItem().getInventory().setOpen( true );

            getEntityController().getEchoes().txOpenContainer( ic, emote );

            return CommandExecutionResult.OK;
        case LOCK:
            if ( ic.getLockController() == null ) {
                getEntityController().tx( "There's no apparent way to lock " + ic.getShortDesc() + "." );
                return CommandExecutionResult.OK;
            }
            if ( ic.getItem().getInventory().isOpen() ) {
                getEntityController().tx( ic.getShortDesc() + " needs to be closed first." );
                return CommandExecutionResult.OK;
            }
            if ( ic.isLockable() && ic.getLockController().isLocked() ) {
                getEntityController().tx( ic.getShortDesc() + " is already locked." );
                return CommandExecutionResult.OK;
            }
            {
                ItemController possibleKey = getEntityController().getInventoryController().findKeyForContainer( ic );
                if ( possibleKey != null ) {
                    ic.getLockController().setLocked( true );
                    getEntityController().getEchoes().txLockContainer( ic, possibleKey, emote );
                    return CommandExecutionResult.OK;
                }
            }
            getEntityController().tx( "You don't seem to be carrying anything to lock " + ic.getShortDesc() + " with." );
            return CommandExecutionResult.OK;
        case UNLOCK:
            if ( ic.getLockController() == null ) {
                getEntityController().tx( "There's no apparent way to unlock " + ic.getShortDesc() + "." );
                return CommandExecutionResult.OK;
            }
            if ( ic.getItem().getInventory().isOpen() ) {
                getEntityController().tx( ic.getShortDesc() + " is already open!" );
                return CommandExecutionResult.OK;
            }
            if ( ic.isLockable() && !ic.getLockController().isLocked() ) {
                getEntityController().tx( ic.getShortDesc() + " is not locked." );
                return CommandExecutionResult.OK;
            }

            {
                ItemController possibleKey = ic.getLockController().unlocksWith( getEntityController().getInventoryController() );
                if ( possibleKey != null ) {
                    ic.getLockController().setLocked( false );
                    getEntityController().getEchoes().txUnlockContainer( ic, possibleKey, emote );
                    return CommandExecutionResult.OK;
                }
            }

            getEntityController().tx( "You don't seem to be carrying anything to unlock " + ic.getShortDesc() + " with." );
            return CommandExecutionResult.OK;
        default:
            throw new IllegalArgumentException( "Container manipulation action with unknown manipulation type." );
        }
    }

    @Override
    public ManipulationContainerInfo getInfo() {
        return (ManipulationContainerInfo) super.getInfo();
    }
}
